package org.sag.gui;


import org.umu.editor.VentanaMensajes;
import org.xml.sax.SAXException;

import javax.swing.*;

import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;

public class XPA extends JFrame implements ItemListener, ActionListener{

	protected Action newAction, openAction, saveAction, saveAsAction, checkSchemaAction;
	protected Action generateTestsAction, runTestsAction;
	protected Action generateMutantsAction, runMutantsAction;
	protected JCheckBoxMenuItem[] items;

	VentanaMensajes vm = new VentanaMensajes();
	boolean showVersionWarning = true;

	protected JTabbedPane mainTabbedPane;
	protected PolicyPanel policyPanel;
	protected TestPanel testPanel;
	protected MutationPanel mutationPanel;

	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				try {
					// turn off bold fonts
					// UIManager.put("swing.boldMetal", Boolean.FALSE);

					// re-install the Metal Look and Feel
					// UIManager.setLookAndFeel(new
					// javax.swing.plaf.metal.MetalLookAndFeel());
				} catch (Exception exception) {
					exception.printStackTrace();
				}
				XPA frame = new XPA();
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				frame.pack();
				frame.setVisible(true);
			}
		});
	}
	
	public XPA(String fileName) throws SAXException, IOException {
		try {
			setDefaultCloseOperation(DISPOSE_ON_CLOSE);
			init();
			if (new File(fileName).exists()) {
				vm.getPrintStream().println("Analyzing file:" + fileName);
				policyPanel.setPolicyTreeModel(fileName);
			} else {
				policyPanel.newFile();
			}
			policyPanel.setWorkingPolicyFile(new File(fileName));
			setTitle("UMU-XACML-Editor - " + getWorkingPolicyFile().getName());
		} catch (SAXException exc) {
			JOptionPane.showMessageDialog(this, exc.toString());
			throw exc;
		} catch (IOException exc) {
			JOptionPane.showMessageDialog(this, exc.toString());
			throw exc;
		} catch (Exception exception) {
			exception.printStackTrace();
		}
	}

	public XPA() {
		try {
			setDefaultCloseOperation(EXIT_ON_CLOSE);
			init();
			policyPanel.newFile();
		} catch (Exception exception) {
			exception.printStackTrace();
		}
	}

    /** Returns an ImageIcon, or null if the path was invalid. */
    protected ImageIcon createNavigationIcon(String imageName) {
        String imgLocation = "org/umu/icons/"  + imageName + ".gif";
        java.net.URL imageURL= this.getClass().getClassLoader().getResource(imgLocation);      
        if (imageURL == null) {
            System.err.println("Resource not found: " + imgLocation);
            return null;
        } else {
            return new ImageIcon(imageURL);
        }
    }

    public JMenuBar createMenuBar() {
        JMenuBar menuBar = new JMenuBar();
        menuBar.add(createPolicyMenu());
        menuBar.add(createTestMenu());
        menuBar.add(createMutationMenu());
        menuBar.add(createDebuggingMenu());
        menuBar.add(createCombiningAlgorithmsMenu());
        menuBar.add(createHelpMenu());
        return menuBar;
    }

    private void createActions(){
        newAction =   new NewAction(  "New",
                createNavigationIcon("new"),
                "New", 
                new Integer(KeyEvent.VK_N));
        openAction =   new OpenAction(  "Open...",
                                        createNavigationIcon("open"),
                                        "Open", 
                                        new Integer(KeyEvent.VK_O));
        saveAction = new SaveAction("Save",
                                        createNavigationIcon("save"),
                                        "Save", 
                                        new Integer(KeyEvent.VK_S));
        saveAsAction = new SaveAsAction("Save As...",
                createNavigationIcon("saveas"),
                "SaveAs", 
                new Integer(KeyEvent.VK_A));
        checkSchemaAction = new CheckSchemaAction("Check Schema...",
                createNavigationIcon("CheckSchema"),
                "CheckSchema", 
                new Integer(KeyEvent.VK_C));        

		generateTestsAction = new GenerateTestsAction("Generate tests...",
				createNavigationIcon("generatetests"), "GenerateTests",
				new Integer(KeyEvent.VK_G));
		
		runTestsAction = new RunTestsAction("Run tests...",
				createNavigationIcon("runtests"), "RunTests", new Integer(
						KeyEvent.VK_R));

		generateMutantsAction = new GenerateMutantsAction("Generate mutants...",
				createNavigationIcon("generatemutants"), "GenerateMutants",
				new Integer(KeyEvent.VK_T));
		
		runMutantsAction = new RunMutantsAction("Run mutants...",
				createNavigationIcon("runmutants"), "RunMutants", new Integer(
						KeyEvent.VK_U));

    }
    
    public void createToolBar() {
        Insets margins = new Insets(1, 1, 1, 1); 

    	JButton button = null;
        JToolBar toolBar = new JToolBar();
        add(toolBar, BorderLayout.PAGE_START);

        //new button
        button = new JButton(newAction);
        button.setMargin(margins);
    	button.setBorderPainted(false);


        if (button.getIcon() != null) {
            button.setText(""); //an icon-only button
        }
        toolBar.add(button);
        
        //open button
        button = new JButton(openAction);
        button.setMargin(margins);
    	button.setBorderPainted(false);
        if (button.getIcon() != null) {
            button.setText(""); //an icon-only button
        }
        toolBar.add(button);

        //save button
        button = new JButton(saveAction);
        button.setMargin(margins);
    	button.setBorderPainted(false);
        if (button.getIcon() != null) {
            button.setText(""); //an icon-only button
        }
        toolBar.add(button);

    }
    
    protected JMenu createPolicyMenu() {
        JMenuItem menuItem = null;
        JMenu fileMenu = new JMenu("Policy");
        Action[] actions = {newAction, openAction, saveAction, saveAsAction, checkSchemaAction};
        for (int i = 0; i < actions.length; i++) {
            menuItem = new JMenuItem(actions[i]);
            menuItem.setIcon(null); //arbitrarily chose not to use icon
            fileMenu.add(menuItem);
        }
        fileMenu.addSeparator();
        fileMenu.add(createMenuItem("Exit"));
        return fileMenu;
    }


    protected JMenuItem createMenuItem(String menuName){
        JMenuItem menuItem = new JMenuItem(menuName);
        menuItem.setActionCommand(menuName);
        menuItem.addActionListener(this);
        return menuItem;
    }
    
    protected JMenu createEditMenu() {
        JMenu editMenu = new JMenu("Edit");
        JMenuItem[] editItems = new JMenuItem[5];

        editItems[0] = new JMenuItem("Cut");
        editItems[1] = new JMenuItem("Copy");
        editItems[2] = new JMenuItem("Paste");
        editItems[3] = new JMenuItem("Find");
        editItems[4] = new JMenuItem("Replace");

        for (int i = 0; i < editItems.length; i++) {
            editItems[i].addItemListener(this);
            editMenu.add(editItems[i]);
        }

        return editMenu;
    }

    protected JMenu createTestMenu() {
        JMenu testMenu = new JMenu("Test");
        Action[] actions = {generateTestsAction, runTestsAction};
        for (int i = 0; i < actions.length; i++) {
            JMenuItem menuItem = new JMenuItem(actions[i]);
            menuItem.setIcon(null); //arbitrarily chose not to use icon
            testMenu.add(menuItem);
        }
        
        JMenuItem coverageItem = new JMenuItem("Evaluate coverage");
        testMenu.add(coverageItem);        
        return testMenu;
    }

    protected JMenu createMutationMenu() {
        JMenu mutationMenu = new JMenu("Mutation");       
        Action[] actions = {generateMutantsAction, runMutantsAction};
        for (int i = 0; i < actions.length; i++) {
            JMenuItem menuItem = new JMenuItem(actions[i]);
            menuItem.setIcon(null); 
            mutationMenu.add(menuItem);
        }        
        return mutationMenu;
    }

    protected JMenu createDebuggingMenu() {
        JMenu debuggingMenu = new JMenu("Debugging");
        return debuggingMenu;
    }

    protected JMenu createCombiningAlgorithmsMenu() {
        JMenu caMenu = new JMenu("Algorithms");
        return caMenu;
    }

    protected JMenu createHelpMenu() {
        JMenu caMenu = new JMenu("Help");
        return caMenu;
    }

    public void itemStateChanged(ItemEvent e) {
        JCheckBoxMenuItem mi = (JCheckBoxMenuItem)(e.getSource());
        boolean selected = (e.getStateChange() == ItemEvent.SELECTED);
        if (mi == items[0]) {
            openAction.setEnabled(selected);
        } else if (mi == items[1]) {
            saveAction.setEnabled(selected);
        }
    }

    public class NewAction extends AbstractAction {
        public NewAction(String text, ImageIcon icon,
                          String desc, Integer mnemonic) {
            super(text, icon);
            putValue(SHORT_DESCRIPTION, desc);
            putValue(MNEMONIC_KEY, mnemonic);
        }
        public void actionPerformed(ActionEvent e) {
        	policyPanel.newFile();
        }
    }

    public class OpenAction extends AbstractAction {
        public OpenAction(String text, ImageIcon icon,
                          String desc, Integer mnemonic) {
            super(text, icon);
            putValue(SHORT_DESCRIPTION, desc);
            putValue(MNEMONIC_KEY, mnemonic);
        }
        public void actionPerformed(ActionEvent e) {
        	policyPanel.openFile();
        }
    }

    public class SaveAction extends AbstractAction {
        public SaveAction(String text, ImageIcon icon,
                            String desc, Integer mnemonic) {
            super(text, icon);
            putValue(SHORT_DESCRIPTION, desc);
            putValue(MNEMONIC_KEY, mnemonic);
        }
        public void actionPerformed(ActionEvent e) {
        	policyPanel.saveFile();
        }
    }

    public class SaveAsAction extends AbstractAction {
        public SaveAsAction(String text, ImageIcon icon,
                            String desc, Integer mnemonic) {
            super(text, icon);
            putValue(SHORT_DESCRIPTION, desc);
            putValue(MNEMONIC_KEY, mnemonic);
        }
        public void actionPerformed(ActionEvent e) {
        	policyPanel.saveAsFile();
        }
    }

    public class CheckSchemaAction extends AbstractAction {
        public CheckSchemaAction(String text, ImageIcon icon,
                            String desc, Integer mnemonic) {
            super(text, icon);
            putValue(SHORT_DESCRIPTION, desc);
            putValue(MNEMONIC_KEY, mnemonic);
        }
        public void actionPerformed(ActionEvent e) {
        	policyPanel.checkSchema();
        }
    }
	
    public class GenerateTestsAction extends AbstractAction {
        public GenerateTestsAction(String text, ImageIcon icon,
                            String desc, Integer mnemonic) {
            super(text, icon);
            putValue(SHORT_DESCRIPTION, desc);
            putValue(MNEMONIC_KEY, mnemonic);
        }
        public void actionPerformed(ActionEvent e) {
        	testPanel.generateTests();
        }
    }

    public class RunTestsAction extends AbstractAction {
        public RunTestsAction(String text, ImageIcon icon,
                            String desc, Integer mnemonic) {
            super(text, icon);
            putValue(SHORT_DESCRIPTION, desc);
            putValue(MNEMONIC_KEY, mnemonic);
        }
        public void actionPerformed(ActionEvent e) {
        	testPanel.runTests();
        }
    }

    public class GenerateMutantsAction extends AbstractAction {
        public GenerateMutantsAction(String text, ImageIcon icon,
                            String desc, Integer mnemonic) {
            super(text, icon);
            putValue(SHORT_DESCRIPTION, desc);
            putValue(MNEMONIC_KEY, mnemonic);
        }
        public void actionPerformed(ActionEvent e) {
        	mutationPanel.generateMutants();
        }
    }

    public class RunMutantsAction extends AbstractAction {
        public RunMutantsAction(String text, ImageIcon icon,
                            String desc, Integer mnemonic) {
            super(text, icon);
            putValue(SHORT_DESCRIPTION, desc);
            putValue(MNEMONIC_KEY, mnemonic);
        }
        public void actionPerformed(ActionEvent e) {
        	mutationPanel.runMutants();
        }
    }

 
	private void createMainTabbedPane(){
        policyPanel = new PolicyPanel(this);
        testPanel = new TestPanel(this);
        mutationPanel = new MutationPanel(this);
        mainTabbedPane = new JTabbedPane();
        mainTabbedPane.setBorder(BorderFactory.createEtchedBorder(0));
        mainTabbedPane.addTab("Policy",createNavigationIcon("images/policy.gif"), policyPanel);
        mainTabbedPane.addTab("Test",createNavigationIcon("images/test.gif"), testPanel);
        mainTabbedPane.addTab("Mutation",createNavigationIcon("images/mutation.gif"), mutationPanel);
//        mainTabbedPane.addChangeListener(this);		
    	mainTabbedPane.setSelectedComponent(policyPanel);
	}

	private void init() throws Exception {        
		setSize(new Dimension(1024, 800));
        createMainTabbedPane();
        createActions();
		
 		JPanel contentPane = (JPanel) getContentPane();
 		contentPane.setLayout(new BorderLayout());
		contentPane.add(mainTabbedPane, BorderLayout.CENTER);

		JScrollPane jsp = new JScrollPane(vm);
		jsp.setPreferredSize(new Dimension(this.getWidth(), (int) (this.getHeight() * 0.2)));
		contentPane.add(jsp, BorderLayout.SOUTH);
		
		setJMenuBar(createMenuBar());
		
		createToolBar();
		if (getWorkingPolicyFile() != null) {
			setTitle("XACML Policy Analyzer - " + getWorkingPolicyFile().getName());
		} else {
			setTitle("XACML Policy Analyzer - Unnamed");
		}
	}

	
	protected void exit(){
		policyPanel.saveChanged();
		this.dispose();		
	}
	
	public VentanaMensajes getVM(){
		return vm;
	}

	public void println(String string){
		vm.getPrintStream().println(string);
	}
	
	public File getWorkingPolicyFile(){
		return policyPanel.getWorkingPolicyFile();
	}

	
	public void actionPerformed(ActionEvent e) {
		if (e.getActionCommand().equalsIgnoreCase("Exit")) {
			windowClosing();
		}
	}

	public void windowClosing() {
		policyPanel.windowClosing();
		this.dispose();
	}

}


class MiWindowAdapter extends WindowAdapter {
	private XPA adaptee;

	MiWindowAdapter(XPA adaptee) {
		this.adaptee = adaptee;
	}

	public void windowClosing(WindowEvent e) {
		adaptee.windowClosing();
	}
}
